﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using InseSoft.Infraestructure;
using InseSoft.Models;
using InseSoft.Services;
using InseSoft.Tests.Unit;
using InseSoft.ViewModels;
using InseSoft.ViewModels.Events;
using Insesoft.Entities;
using InseSoft.UIControllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ninject;
using Ninject.MockingKernel;
using Ninject.MockingKernel.Moq;

namespace InseSoft.Tests
{
    public class TestHelper
    {
        public static IKernel SetupDIKernel()
        {
            var kernel = new MoqMockingKernel();
            kernel.Bind<ICatalogSearchViewModel>().To<CatalogSearchViewModel>();
            kernel.Bind<IEventPublisher>().To<EventPublisher>().InSingletonScope();
            kernel.Bind<IInseContext>().To<FakeDbContext>();
            kernel.Bind<IDialogService>().ToMock();
            kernel.Bind<LoginViewModel>().ToSelf();
            kernel.Bind<MainViewModel>().ToSelf();
            kernel.Bind<IWindowLauncher>().ToMock();
            
            DIFactory.Kernel = kernel;
            return kernel;
        }

        public static void AssertAreListsEqual(IList<EntidadCatalogo> list1, IList<EntidadCatalogo> list2)
        {
            Assert.AreEqual(list1.Count, list2.Count, "Lists have different number of elements");
            for (var i = 0; i < list1.Count; i++)
                Assert.AreEqual(list1[i], list2[i]);
        }

        public static void PopulateEntity(object instance)
        {
            foreach (PropertyInfo property in GetEntityProperties(instance))
            {
                var value = GetPropertyUniqueValue(property);
                if (value != null)
                    ReflectionHelper.SetPropertyValue(instance, property.Name, GetPropertyUniqueValue(property));
            }
        }

        private static object GetPropertyUniqueValue(PropertyInfo property)
        {
            var typeName = property.PropertyType.Name.ToLower();
            if (property.PropertyType.FullName != null)
            {
                var typeFullName = property.PropertyType.FullName.ToLower();
                if (typeFullName.Contains("nullable") && typeFullName.Contains("datetime"))
                    typeName = "datetime";
            }
            return GetValueByType(property, typeName);
        }

        private static object GetValueByType(PropertyInfo property, string typeName)
        {
            switch (typeName)
            {
                case "string":
                    return property.Name;
                case "datetime":
                    return DateTime.MinValue.AddSeconds(property.GetHashCode());
                case "bool":
                case "boolean":
                    return true;
                case "int":
                case "int32":
                case "double":
                case "decimal":
                    return property.GetHashCode();
                case "cliente":
                    return new Cliente();
                case "empresa":
                    return new Empresa();
                case "linea":
                    return new Linea();
                case "material":
                    return new Material();
                case "tipocambio":
                    return new TipoCambio();
                case "tipoproducto":
                    return new TipoProducto();
                case "usuario":
                    return new Usuario();
                case "vendedor":
                    return new Vendedor();
                
            }
            return null;
        }

        private static IEnumerable GetEntityProperties(object instance)
        {
            var exclusions = new[] {"ShouldCheckLength"};
            return instance.GetType().GetProperties()
                .Where(p => p.CanWrite 
                    && !exclusions.Contains(p.Name)
                    && p.Name != "Id");
        }
    }
}
